package com.gopay.cashier.web.controller;

import com.gopay.common.constants.SubAccountConstants;
import com.gopay.common.cps.dao.order.CpsGeneralReceiptOrderQueryDAO;
import com.gopay.common.cps.dao.trans.CpsReceiptSplitDtlQueryDAO;
import com.gopay.common.domain.cps.CpsGenReceiptOrder;
import com.gopay.common.domain.cps.CpsReceiptSplitDtl;
import com.gopay.common.util.RequestUtils;
import com.gopay.cashier.common.exception.WebException;
import com.gopay.cashier.domain.bean.LoginUser;
import com.gopay.cashier.service.gsrt.GsrtService;
import com.gopay.cashier.service.riskcontrol.CallRiskControlService;
import com.gopay.cashier.web.command.BankPayChannelCommand;
import com.gopay.cashier.web.command.BankPayWay;
import com.gopay.cashier.web.command.OrderInfo;
import com.gopay.cashier.web.utils.BisBankBusinessProdConvertUtil;
import com.gopay.cashier.web.utils.CashierConfig;
import com.gopay.common.constants.Constants;
import com.gopay.common.constants.YnFlag;
import com.gopay.common.constants.cust.CustCorpInfoConstants;
import com.gopay.common.constants.cust.CustPersonInfoConstants;
import com.gopay.common.constants.cust.UserInfoConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.constants.trans.*;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.domain.UserInfo;
import com.gopay.common.domain.acps.AcctStatus;
import com.gopay.common.domain.acps.FrezCode;
import com.gopay.common.domain.acps.model.AcctMastBean;
import com.gopay.common.domain.bis.BisBankInfoMain;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.domain.cust.CustCorpInfo;
import com.gopay.common.domain.cust.CustPersonInfo;
import com.gopay.common.domain.poundage.PoundageRes;
import com.gopay.common.exception.GopayException;
import com.gopay.common.user.manager.UserInfoQueryManager;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.ReflectionUtil;
import com.gopay.remote.order.MainOrderField;
import com.gopay.remote.order.Tran01813OrderCheckAndUpdateRemoteService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Administrator
 * 银行支付渠道
 * @BisRequestController
 */
@Controller
public class BankPayChannelController  extends BaseController {

	@Autowired
	private CpsGeneralReceiptOrderQueryDAO cpsGeneralReceiptOrderQueryDAO;

	@Autowired
	private CpsReceiptSplitDtlQueryDAO cpsReceiptSplitDtlQueryDAO;

	@Resource(name="callRiskControlService")
    private CallRiskControlService callRiskControlService;
    
    @Resource(name="userInfoQueryManager")
    private UserInfoQueryManager userInfoQueryManager;
    
    @Resource(name="gsrtService")
    private GsrtService gsrtService;


	@Resource(name = "tran01813OrderCheckAndUpdateService")
	private Tran01813OrderCheckAndUpdateRemoteService tran01813OrderCheckAndUpdateRemoteService;

	 @RequestMapping("/pay/bpc.shtml")
	 public ModelAndView execute(BankPayChannelCommand command) throws GopayException{
	     printRequest("bankPayChannelController--bankPayChannel,command="+command);
        //add by fanghw 20160524
        if(StringUtils.isNotBlank(command.getPayBankCodeAll())){
            String selBankCode=command.getPayBankCodeAll().split("-")[1];
            if(PayChannel._01.value.equals(command.getPayChannel())){
                command.setPersonalPayBankCode(selBankCode);
            }else if(PayChannel._51.value.equals(command.getPayChannel())){
                command.setCorpPayBankCode(selBankCode);
            }
        }
        
        
        String orderId = getRequest().getParameter(GOPAY_ORDER_ID);
		CpsGenMainOrder order = getMainOrder(orderId, true);
		LoginUser loginUser = getLoginUser();
		/**
		 * G商融通做用户登录
		 */
		if(StringUtils.equals(order.getGatewaySource(), GatewaySource.GATEWAY_SOURCE_09.toString())){
			UserInfo userInfo = userInfoQueryManager.getUserInfoByCustId(order.getPayCustId());
			loginUser = new LoginUser();
			loginUser.setUser(userInfo);;
		}
        // 验证
        if (!validate(command, order,loginUser)) {
            return back(command, order);
        }
         //防钓鱼校验
         ModelAndView check = checkAntiPhish(command,"/pay/bpc.shtml?orderKey="+getRequest().getParameter("orderKey")+"&orderId="+orderId);
         if(check != null)
             return check;

         updateOrder(command, order);

		 /**** add by sh.jiao 20170922 增加云账户子账户收款修改关联订单交易金额，手续费金额等字段更新逻辑 start ****/
		 /*if (IntTxnCd._01813.value.equals(order.getGopayIntTxnCd())) {
			 String resultCode = tran01813OrderCheckAndUpdateRemoteService.checkAndUpdateOrder(order.getGopayOrderId());
			 if (!ProcCodeConstants.PROC_CODE_000S1000.equals(resultCode)) {
				 throw new GopayException(resultCode);
			 }
		 }*/
		 /**** add by sh.jiao 20170922 增加云账户子账户收款修改关联订单交易金额，手续费金额等字段更新逻辑 end ****/
         
        // 差额支付、入金
        if ((loginUser!=null && (command.isShortfallPay() || StringUtils.equals(order.getGopayIntTxnCd(), IntTxnCd._00200.value))) || (isP2P(order))) {
            // 必须先更新原订单，再创建充值订单，因为创建充值订单要使用原订单的信息，比如pay_acct
//            updateOrder(command, order);
            /** 登陆后支付的情况，创建充值订单. 因为手续费数据有更新，这里必须重新加载最新订单数据。 */
            order = getMainOrder(order.getGopayOrderId(), true);

            CpsGenMainOrder inchargeOrder = order;
            if(!StringUtils.equals(order.getGopayIntTxnCd(), IntTxnCd._01300.value)){
                //p2p转账、入金交易，先生成充值订单
                BankPayChannelCommand inchargeCommand = saveInchargeOrder(command, order);
                inchargeOrder = getMainOrder(inchargeCommand.getInChargeOrderId(), true);
                
                //对充值订单做RIMS风控监控
//                logger.info("对充值订单做RIMS风控监控>>>>>>>>>>>");
                //rimsProcess(inchargeOrder);
                
                
            }
            BisBankInfoMain bank = getBank(command.getPayBankCode(), true);
            String needPaypwd = needPaypwd(order.getGopayOrderId());
            OrderInfo orderInfo = getOrderInfo(order.getGopayOrderId());
            
        	//RIMS风控监控
    		//必须在更新订单之后，需要updateOrder获取订单信息
    		//rimsProcess(getMainOrder(order.getGopayOrderId(), true));

			//调用风控二期服务校验 add by xuhui 20160811
			callRiskControlService.assess(order.getGopayOrderId(), order.getPayChannel(), null, null);

            if(isP2P(order)){
                return payConfirm(inchargeOrder,bank,orderInfo);
            }else{
                return shortfallPay(command.isShortfallPay(),inchargeOrder,bank, needPaypwd, orderInfo, order.getTotalOrderAmt());
            }
        } else{
        	//RIMS风控监控
    		//必须在更新订单之后，需要updateOrder获取订单信息
    		order = getMainOrder(order.getGopayOrderId(), true);
    		//rimsProcess(order);

            //调用风控二期服务校验 add by xuhui 20160811
            callRiskControlService.assess(order.getGopayOrderId(), order.getPayChannel(), null, null);

            
            //目前只有充值交易进行风控校验
            if(isInchargeOrder(order)){
                //风控额度校验
                checkTranAmtLimit();
            }
            return directBankPay(command);
        }
	 }

	  
	 private boolean validate(BankPayChannelCommand command, CpsGenMainOrder order,LoginUser loginUser) throws GopayException {
		 	HttpServletRequest request = getRequest();
	        if (StringUtils.isBlank(command.getPayBankCode())) {
	            logger.error(this.getClass() + "没有选择银行！ no bank selected!!" + command);
	            request.setAttribute(FIELD_ERR_MSG, "请选择银行");
	            return false;
	        }
	        if (StringUtils.isBlank(command.getPayChannel())) {
	        	logger.error(this.getClass() + "没有选择银行类型！ no paychannel selected!!" + command);
	        	request.setAttribute(FIELD_ERR_MSG, "请选择银行类型");
	        	return false;
	        }
	        if (null == order) {
	            logger.error("找不到订单！order not exits!" + command);
	            throw new WebException(ProcCodeConstants.PROC_CODE_100E5041);
	        }
	        if (TxnStaCode.TXN_STA_CD_20000.value == (order.getTxnStaCd())) {
	            logger.error("订单已经支付成功，中断处理！order is finished!" + command + ", " + order);
	            throw new WebException(ProcCodeConstants.PROC_CODE_100E5042);
	        }
	        if (loginUser!=null) {
	        	//校验付款方
	        	if(isInchargeOrder(order) || isP2P(order)){
                    if(StringUtils.equals(order.getGopayIntTxnCd(), IntTxnCd._01300.value) && !StringUtils.equals(loginUser.getUser().getCustId(), order.getMainRecvCustId())){
                        //充值交易只能给自己付款
                        request.setAttribute(FIELD_ERR_MSG, "充值交易异常，不能由他人代为充值");
                        return false;
                    }else if(StringUtils.equals(order.getGopayIntTxnCd(), IntTxnCd._01302.value) &&  !StringUtils.equals(loginUser.getUser().getCustId(), order.getPayCustId())){
                        request.setAttribute(FIELD_ERR_MSG, "转账交易异常，不能由他人代为转账");
                        return false;
                    }else if(isInchargeOrder(order) && !StringUtils.equals(loginUser.getUser().getCustId(), order.getMainRecvCustId())){
	        			request.setAttribute(FIELD_ERR_MSG, "充值交易异常，不能由他人代为充值");
		                return false;
	        		}
	        	}else{
	        		if(StringUtils.equals(loginUser.getUser().getCustId(), order.getMainRecvCustId()) || (StringUtils.isNotBlank(command.getGopayAcctId()) && StringUtils.equals(command.getGopayAcctId(), order.getMainRecvAcct()))){
		        		request.setAttribute(FIELD_ERR_MSG, "不能给自己付款，请退出重新登录");
		                return false;
		        	}
	        	}
	            UserInfo userInfo = loginUser.getUser();
	            if (null == userInfo || UserInfoConstants.USER_STAT_CANCEL.equals(userInfo.getUserStat())) {
	                logger.error("用户不存在或尚未登录！user not exist or not login! " + request.getRemoteUser());
	                throw new WebException(ProcCodeConstants.PROC_CODE_100E2001);
	            }
	            if (!UserInfoConstants.USER_STAT_NORMAL.equals(userInfo.getUserStat())) {
	                logger.error("用户状态异常：" + userInfo.getCustId());
	                throw new WebException(ProcCodeConstants.PROC_CODE_100E2002);
	            }
	            String userType = userInfo.getUserType();
	            if (UserInfoConstants.USER_TYPE_PERSON.equals(userType)) {
	                CustPersonInfo info = custPersonInfoQueryManager.get(userInfo.getCustId());
	                if (info == null || CustPersonInfoConstants.CUST_STAT_CANCEL.equals(info.getCustStat())) {
	                    throw new WebException(ProcCodeConstants.PROC_CODE_100E5001);
	                }
	                if (!CustPersonInfoConstants.CUST_STAT_NORMAL.equals(info.getCustStat())) {
	                    throw new WebException(ProcCodeConstants.PROC_CODE_100E5002);
	                }
	            } else if (userType.startsWith("2")) {
	                CustCorpInfo info = custCorpInfoService.get(userInfo.getCustId());
	                if (info == null || CustCorpInfoConstants.CORP_STAT_CANCEL.toString().equals(info.getCorpStat())) {
	                    throw new WebException(ProcCodeConstants.PROC_CODE_100E5001);
	                }
	                if (!CustCorpInfoConstants.CORP_STAT_NORMAL.toString().equals(info.getCorpStat())) {
	                    throw new WebException(ProcCodeConstants.PROC_CODE_100E5002);
	                }
	            } else {
	                throw new WebException(ProcCodeConstants.PROC_CODE_100E1027);
	            }
	        }else{
	        	//充值交易须登录
	        	if(isInchargeOrder(order)){
	        		logger.error("InCharge 00500 need login!!");
	        		request.setAttribute(FIELD_ERR_MSG, ProcCodeConstants.PROC_CODE_100W1006);
	                return false;
	        	}
	        	//入金交易须登录
	        	if(StringUtils.equals(order.getGopayIntTxnCd(), IntTxnCd._00200.value)){
	        		logger.error("InCharge 00200 need login!!");
	        		request.setAttribute(FIELD_ERR_MSG, ProcCodeConstants.PROC_CODE_100W1006);
	        		return false;
	        	}
	        }
	        
        	//校验收款方
        	 checkRecvCustStatus(0, order.getMainRecvCustId());
        	 AcctMastBean acct = acctTransService.getAccount(order.getMainRecvAcct());
             if (null == acct) {
                 logger.error("账户不存在,acctId=" + order.getMainRecvAcct());
                 throw new WebException(ProcCodeConstants.PROC_CODE_100E6012);
             }
             if (AcctStatus.F.equals(acct.getAccStatus())) {
                 if (FrezCode.CRE.equals(acct.getFrezCode()) || FrezCode.FUL.equals(acct.getFrezCode())) {
                     throw new GopayException(ProcCodeConstants.PROC_CODE_100E3025, "账户[" + order.getMainRecvAcct()
                             + "]处于冻结状态[" + acct.getFrezCode() + "]，无法入款");
                 }
             }
	        return true;
	    }
	 
	 
	    private ModelAndView back(BankPayChannelCommand command, CpsGenMainOrder order)throws WebException {
	    	HttpServletRequest request = getRequest();
	    	ModelAndView mav = new ModelAndView();
	    	mav.addObject("orderId", order.getGopayOrderId());
	    	mav.addObject("ch", command.getPayChannel());
        	if(isInchargeOrder(order)){
        		mav.addObject("inc", "y");
    		}
        	if(request.getAttribute(FIELD_ERR_MSG)!=null && StringUtils.isNotBlank((String)request.getAttribute(FIELD_ERR_MSG))){
        		//未登录，跳转登录
        		if(ProcCodeConstants.PROC_CODE_100W1006.equals((String)request.getAttribute(FIELD_ERR_MSG))){
        			mav.addObject("gopayUser", getGopayUser());
        			mav.setViewName("redirect:/logout.shtml");
        			return mav;
        		}else{
        			request.getSession().setAttribute(FIELD_ERR_MSG, request.getAttribute(FIELD_ERR_MSG));
        		}
        	}
        	mav.setViewName("redirect:/pay/info.shtml");
            return mav;
	    }
	    
	    private PayChannel getPayChannel(BankPayChannelCommand command, CpsGenMainOrder order){
	    	PayChannel payChannel = PayChannel.get(command.getPayChannel());
	    	String payAcct = command.getGopayAcctId();
	    	LoginUser loginUser = getLoginUser();
	    	if(loginUser!=null){
	    		UserType userType = UserType.get(loginUser.getUser().getUserType());
		        //差额支付
		        if (StringUtils.isNotBlank(payAcct) && (command.isShortfallPay() || StringUtils.equals(order.getGopayIntTxnCd(), IntTxnCd._00200.value))) {
		            if (UserType.Person.equals(userType)) {
			            payChannel = PayChannel._02;
			        } else {
			            payChannel = PayChannel._52;
			        }
		        }
	    	}
	    	return payChannel;
	    }

	    /**
	     * 根据支付渠道等更新原订单信息,订单状态
	     */
	    private void updateOrder(BankPayChannelCommand command, CpsGenMainOrder order) throws WebException {
	        Map<MainOrderField, String> values = new HashMap<MainOrderField, String>();
	        LoginUser loginUser = getLoginUser();
	        PayChannel payChannel = getPayChannel(command, order);
	        //计算手续费
			//add by jianghoup 增加单银行特例手续费中的银行代码 20160908
			String bankCode =null;
			logger.info("付款通道为："+command.getPayChannel());
			if(PayChannel._01.value.equals(command.getPayChannel())){
				bankCode = command.getPersonalPayBankCode();
			}else if(PayChannel._51.value.equals(command.getPayChannel())){
				bankCode = command.getCorpPayBankCode();
			}
			logger.info("增加特例银行，编码为："+bankCode);

	    	PoundageRes p = getPoundageRes(order, payChannel,bankCode);
	    	
	        if(loginUser!=null){
	        	values.put(MainOrderField.PAY_CUST_ID, loginUser.getUser().getCustId());
	        }
            values.put(MainOrderField.PAY_CHANNEL, payChannel.toString());
            values.put(MainOrderField.OUT_STLM_ID, command.getPayBankCode());
            if(!isP2P(order)){
                if(StringUtils.equals(order.getGopayIntTxnCd(), IntTxnCd._00200.value)){
                    values.put(MainOrderField.PAY_ACCT, command.getGopayAcctId());
                }else{
                    values.put(MainOrderField.TXN_STA_CD, TxnStaCode.TXN_STA_CD_30101.value + "");
                }
            }

	        values.put(MainOrderField.ORDER_DEAL_AMT, p.getOrderDealAmt().toString());
	        values.put(MainOrderField.ORDER_REAL_FEE_AMT, p.getOrderRealFeeAmt().toString());
	        values.put(MainOrderField.TOTAL_ORDER_AMT, p.getTotalAmt().toString());
	        values.put(MainOrderField.TOTAL_ORDER_FEE_AMT, p.getTotalFeeAmt().toString());
	        values.put(MainOrderField.ORDER_FEE_PAYER, p.getOrderFeePayer().value);

	        /**结算金额： 网银付款更新结算金额字段  系统加固   zhg.zhang 20160712 start**/
	        values.put(MainOrderField.SETTLE_AMT, p.getSettleAmt().toPlainString());
	        /**结算金额： 网银付款更新结算金额字段  系统加固   zhg.zhang 20160712 end**/

			/**远程IP地址 songefengli 20160922**/
			values.put(MainOrderField.REMOTE_IP, RequestUtils.getRemoteRealIpAddr(getRequest()));

	        // 如果是收款方承担手续费，且手续费金额大于订单金额，中断交易，防止实际交易金额为负数。
	        if (OrderFeePayer.REC_PAYER.equals(p.getOrderFeePayer())) {
	            if (1 == p.getTotalFeeAmt().compareTo(order.getMerTxnAmt())) {
	                logger.error("手续费金额大于订单金额，中断交易！pay error: feeAmt[" + p.getTotalFeeAmt() + "]>merTxnAmt["
	                        + order.getMerTxnAmt() + "]! " + command + ", " + order);
	                throw new WebException(ProcCodeConstants.PROC_CODE_100E5055);
	            }

				/*通用分账  added by Chenyu Li at 2018/3/10 start*/
				if(isSplit(order)){
					CpsReceiptSplitDtl cpsReceiptSplitDtl = cpsReceiptSplitDtlQueryDAO.queryPlatformDtlsByGopayOrderId(order.getGopayOrderId());
					logger.error("cpsReceiptSplitDtl = " + cpsReceiptSplitDtl);
					if (cpsReceiptSplitDtl == null) {
						logger.error("平台方没有参与分账，中断交易！pay error: feeAmt[" + p.getTotalFeeAmt() + "]>merTxnAmt["
								+ order.getMerTxnAmt() + "]! " + command + ", " + order);
						throw new WebException(ProcCodeConstants.PROC_CODE_100E1033);
					}
					if (1 == p.getTotalFeeAmt().compareTo(cpsReceiptSplitDtl.getMerTxnAmt())) {
						logger.error("手续费金额大于平台方分账金额，中断交易！pay error: feeAmt[" + p.getTotalFeeAmt() + "]>merTxnAmt["
								+ order.getMerTxnAmt() + "]! " + command + ", " + order);
						throw new WebException(ProcCodeConstants.PROC_CODE_100E1405);
					}
				}
				/*通用分账  added by Chenyu Li at 2018/3/10 end*/
//				BigDecimal subAccountAmt = subAccountInfoService.subAccountSumAmt(order);
//				BigDecimal txnAmt = order.getMerTxnAmt().subtract(p.getTotalFeeAmt());
//				if(subAccountAmt.compareTo(txnAmt) >0){
//					logger.error("分账总金额大于订单金额和手续费金额，中断交易！pay error: feeAmt[" + p.getTotalFeeAmt() + "]>merTxnAmt["
//							+ order.getMerTxnAmt() + "]! " +"subAccountAmt["+subAccountAmt+"]! " + command + ", " + order);
//					throw new WebException(ProcCodeConstants.PROC_CODE_100E1186);
//				}
	        }

			// 云账户子账户收款交易如果普通账户可用余额小于手续费，则抛出异常，账户余额不足 add by sh.jiao 20171020
			if(IntTxnCd._01813.value.equals(order.getGopayIntTxnCd())) {
				AcctMastBean acct = acctTransService.getAccount(order.getMainRecvAcct());
				if(acct == null) {
					logger.error("收款账户不存在,gopayOrderId:"+order.getGopayOrderId());
					throw new WebException(ProcCodeConstants.PROC_CODE_100E5260);
				}
				if (new BigDecimal(acct.getAvaAmt()).compareTo(p.getTotalFeeAmt())<0){
					logger.error("手续费金额大于普通账户可用余额，中断交易，支付失败，请联系平台！pay error: feeAmt[" + p.getTotalFeeAmt() + "]>avaAmt["
							+ acct.getAvaAmt() + "]! " + command + ", " + order);
					throw new WebException(ProcCodeConstants.PROC_CODE_100E5344);
				}
			}

	        /**** add by jiaoshuai 20160901 云账户平台帐号portal充值限制订单金额大于手续费begin ****/
	        // 云账户平台帐号在portal发起充值时，如果交易方案配置为商城承担手续费，则跟收款方承担手续费情况一样，为了避免在续费金额大于订单金额时实际交易金额为负数，需中断交易 
            if (OrderFeePayer.MER_PAYER.equals(p.getOrderFeePayer()) && 
                    GatewaySource.GATEWAY_SOURCE_06.value.equals(order.getGatewaySource()) &&
                    Constants.GOPAY_SYS_MERID.equals(order.getMerId())) {
                if (1 == p.getTotalFeeAmt().compareTo(order.getMerTxnAmt())) {
                    logger.error("手续费金额大于订单金额，中断交易！pay error: feeAmt[" + p.getTotalFeeAmt() + "]>merTxnAmt["
                            + order.getMerTxnAmt() + "]! " + command + ", " + order);
                    throw new WebException(ProcCodeConstants.PROC_CODE_100E5055);
                }
            }
            /**** add by jiaoshuai 20160901 云账户平台帐号portal充值限制订单金额大于手续费end ****/
            
	        try {
	            logger.error("调用cps更新订单状态.BEGIN.call cps update mainOrder." + command + ", " + order + ", " + values);
	            mainOrderUpdateService.payUpdate(order.getGopayOrderId(), values);
	            //如果是G商融通的充值，则去更新G商融通充值业务表
	            if(StringUtils.equals(order.getGatewaySource(), GatewaySource.GATEWAY_SOURCE_09.value)){
	            	gsrtService.updateGsrtRecharge(order.getGopayOrderId());
	            }
	            logger.error("调用cps更新订单状态.END.call cps update mainOrder." + command + ", " + order);
	        } catch (GopayException e) {
	            logger.error("调用cps更新订单状态出错！call cps update mainOrder exception!" + command + ", " + order, e);
	            throw new WebException(e.getErrCode());
	        }
	    }
	    
	    /**
	     * 调用cps创建充值订单
	     * 
	     * @param command
	     * @return
	     * @throws WebException
	     */
	    private BankPayChannelCommand saveInchargeOrder(BankPayChannelCommand command,
	            CpsGenMainOrder order) throws WebException {
	    	BankPayChannelCommand inchargeCommand = new BankPayChannelCommand();
	        ReflectionUtil.copyProperties(inchargeCommand, command);
	        String inchargeOrderId = "";
	        PayChannel payChannel = PayChannel.get(command.getPayChannel());
	        // 计算银行卡实际支付金额，如果是全额支付，则为订单金额；如果是差额支付，则为订单金额减去账户可用余额
	        BigDecimal actualPayAmt = getActualPayAmt(command, order);
	        LoginUser user = getLoginUser();
	        String custId = (null == user || null == user.getUser()) ? "-" : user.getUser().getOperId();
	        try {
	            logger.error("调用cps创建支付充值订单.BEGIN.call cps for saving incharge order." + command);
	            inchargeOrderId = cashierPayCallbackService.saveInchargeOrder(order.getGopayOrderId(),actualPayAmt.toString(), payChannel.value, command.getPayBankCode(), custId);
	            logger.error("调用cps创建支付充值订单.END.call cps for saving incharge order." + inchargeOrderId + ", " + command);
	        } catch (GopayException e) {
	            logger.error("调用cps创建充值订单发生错误！shortfallpay saveInchargeOrder error!" + command, e);
	            throw new WebException(e.getErrCode());
	        }
	        inchargeCommand.setInChargeOrderId(inchargeOrderId);
	        return inchargeCommand;
	    }

	    private ModelAndView directBankPay(BankPayChannelCommand command) throws WebException {
	        // 因为更新了手续费等字段，这里重新查询订单。
	        CpsGenMainOrder order = getMainOrder(getOrderId(), true);
	        OrderInfo orderInfo = getOrderInfo(order.getGopayOrderId());
	        
	        /**系统加固   发送BIS交易金额  1.首先获取结算金额  2.结算金额无值，取总金额     zhg.zhang 20160712 start**/
	        
	        BigDecimal amt=order.getSettleAmt()!=null
	        		&&BigDecimal.ZERO.compareTo(order.getSettleAmt())<0
	        		?order.getSettleAmt():order.getTotalOrderAmt();
	        logger.info("order settleAmt="+order.getSettleAmt()+""
	        		+ ",totalOrderAmt="+order.getTotalOrderAmt()+",orderId="+order.getGopayOrderId());
	        /**系统加固   发送BIS交易金额  1.首先获取结算金额  2.结算金额无值，取总金额     zhg.zhang 20160712 end**/
	        
	        ModelAndView mav = new ModelAndView("pay/bankPayForBis");
	        mav.addObject("orderId", order.getGopayOrderId());
	        //系统加固   发送BIS交易金额  注释原代码
	        //mav.addObject("amount", order.getTotalOrderAmt());
	        mav.addObject("amount", amt);
	        
	        mav.addObject("orderDate", DateUtils.format(order.getGopayTxnTm()));
	        mav.addObject("userType", "");
	        mav.addObject("bank", order.getOutStlmId());
	        mav.addObject("order", orderInfo);
	        mav.addObject("bisUrl", CashierConfig.get(CashierConfig.BIS_URL));
	        mav.addObject("bankBusProd", BisBankBusinessProdConvertUtil.getBisBankBusinessProd(PayChannel.get(command.getPayChannel())).value);
            //银行客户号
            setB2BBankConfig(mav,PayChannel.get(command.getPayChannel()),order.getOutStlmId());

	        getRequest().getSession().removeAttribute(CAS_GOPAY_USER);
	    	getRequest().getSession().removeAttribute(GOPAY_ORDER_ID);
	    	
	        return mav;
	    }
	    
	    private  ModelAndView shortfallPay(boolean isShortfallPay,CpsGenMainOrder inchargeOrder, BisBankInfoMain bank, String needPaypwd,OrderInfo orderInfo, BigDecimal orgOrderAmt) throws WebException {
	        DecimalFormat df = new DecimalFormat("0.00");
	        ModelAndView mav = new ModelAndView("pay/payConfirm");
	        BigDecimal amt = inchargeOrder.getTotalOrderAmt();

	        if (isShortfallPay) {
	            BigDecimal acctPayAmt = orgOrderAmt.subtract(amt);
	            mav.addObject("payWay", BankPayWay.S.name());
	            mav.addObject("payMode", "账户+网银支付");
	            mav.addObject("acctPayAmt", df.format(acctPayAmt));
	            mav.addObject("bankPayAmt", df.format(amt));
	        } else {
	            mav.addObject("payWay", BankPayWay.F.name());
	            mav.addObject("payMode", "网银支付");
	            mav.addObject("payAmt", df.format(amt));
	        }
	        mav.addObject("orderId", inchargeOrder.getGopayOrderId());
	        mav.addObject("bankName", bank.getBankName());
	        mav.addObject("needPaypwd", needPaypwd);// 需要输入支付密码
	        mav.addObject("formhash", setReqAttr(KEY_FORM_HASH, getRandom(32)));// 防止hack
	        mav.addObject("order", orderInfo);
	        mav.addObject("portalUrl", CashierConfig.get("portal.url")+"/gfeature/gTranResultShow.shtml?oid="+orderInfo.getOrderId());
	        return mav;
	    }
	    
	    /**
	     * 计算正确的差额支付金额，同时进行校验
	     */
	    private BigDecimal getActualPayAmt(BankPayChannelCommand command, CpsGenMainOrder order) throws WebException {
	        if (command.isShortfallPay()) {
	            BigDecimal orderAmt = order.getTotalOrderAmt();
	            AcctMastBean acct = acctTransService.getAccount(command.getGopayAcctId());
	            if (null == acct) {
	                logger.error("账户不存在！acctMast not exist!" + command + ", " + order);
	                throw new WebException(ProcCodeConstants.PROC_CODE_000E3001);
	            }
	            BigDecimal acctBalance = new BigDecimal(acct.getAvaAmt());
	            //账户可用余额 + 差额支付金额 = 订单金额
	            if(orderAmt.compareTo(acctBalance)==1){
	            	BigDecimal shortfallPayAmt = orderAmt.subtract(acctBalance);
	            	return shortfallPayAmt;
	            }
	        }else{
	        	// 如果是付款方付手续费，则是商户提交金额加上手续费。
	            return order.getTotalOrderAmt();
	        }
	        logger.error("支付类型错误！wrong payway!" + command + ", " + order);
            throw new WebException(ProcCodeConstants.PROC_CODE_100E5006);
	    }

    private  ModelAndView payConfirm(CpsGenMainOrder inchargeOrder, BisBankInfoMain bank,OrderInfo orderInfo) throws WebException {
        DecimalFormat df = new DecimalFormat("0.00");
        ModelAndView mav = new ModelAndView("pay/p2pPayConfirm");
        BigDecimal amt = inchargeOrder.getTotalOrderAmt();
        mav.addObject("payWay", BankPayWay.F.name());
        mav.addObject("payMode", "网银支付");
        mav.addObject("payAmt", df.format(amt));

        mav.addObject("orderId", inchargeOrder.getGopayOrderId());
        mav.addObject("bankName", bank.getBankName());
        mav.addObject("needPaypwd", YnFlag.n.code);
        mav.addObject("formhash", setReqAttr(KEY_FORM_HASH, getRandom(32)));// 防止hack
        mav.addObject("order", orderInfo);
        mav.addObject("formUrl","/pay/bankConfirm.shtml");
        return mav;
    }
}
